package com.yupi.yupicturebackend.manager.upload;


import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.RandomUtil;
import com.qcloud.cos.model.PutObjectResult;
import com.qcloud.cos.model.ciModel.persistence.ImageInfo;
import com.yupi.yupicturebackend.config.CosClientConfig;
import com.yupi.yupicturebackend.exception.BusinessException;
import com.yupi.yupicturebackend.exception.ErrorCode;
import com.yupi.yupicturebackend.manager.CosManager;
import com.yupi.yupicturebackend.model.dto.file.UploadPictureResult;
import lombok.extern.slf4j.Slf4j;

import javax.annotation.Resource;
import java.io.File;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * 图片上传模板
 * @author xiaodi
 * @date 2025/4/4
 * @Description
 */
@Slf4j
public abstract class PictureUploadTemplate {
    /**
     * 1 兆
     */
    private static final long ONE_M = 1024 * 1024L;
    private static final List<String> ALLOW_FORMAT_LIST = Arrays.asList("jpeg", "jpg", "png", "webp");
    @Resource
    private CosClientConfig cosClientConfig;
    @Resource
    private CosManager cosManager;

    /**
     * 上传文件
     * @param inputSource 文件
     * @param uploadPathPrefix 上传路径前置
     * @return
     */
    public UploadPictureResult uploadPicture(Object inputSource,String uploadPathPrefix){
        //校验图片
        validPicture(inputSource);
        //图片上传地址
        String uuid= RandomUtil.randomString(16);

        String originalFilename=getOriginalFilename(inputSource);
        //自己拼接文件上传路径，而不是使用原始文件名称，可以增加安全性
        String uploadFilename=String.format("%s_%s.%s", DateUtil.formatDate(new Date()),uuid,FileUtil.getSuffix(originalFilename));
        String uploadPath=String.format("/%s/%s",uploadPathPrefix,uploadFilename);
        File file=null;
        try {
            //上传文件
            file=File.createTempFile(uploadPath,null);
            //处理文件来源
            processFile(inputSource,file);
            PutObjectResult putObjectResult = cosManager.putPictureObject(uploadPath, file);
            //获取图片信息对象
            ImageInfo imageInfo = putObjectResult.getCiUploadResult().getOriginalInfo().getImageInfo();
            return buildResult(originalFilename, uploadPath, file, imageInfo);
        } catch (Exception e) {
            log.error("图片上传到对象存储失败",e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"上传失败");
        }finally {
            //临时文件清理
            deleteTempFile(file);
        }

    }

    /**
     *获得输入源的原始文件名
     */

    protected  abstract String getOriginalFilename(Object inputSource) ;

    /**
     *校验输入源
     */
    protected abstract void validPicture(Object inputSource);
    /**
     *处理输入源，并生成本地临时文件
     */
    protected  abstract void processFile(Object inputSource,File file) throws Exception;


    /**
     * 封装返回结果
     * @param originalFilename
     * @param uploadPath
     * @param file
     * @param imageInfo
     * @return
     */
    private UploadPictureResult buildResult(String originalFilename, String uploadPath, File file, ImageInfo imageInfo) {
        //封装返回结果
        int picWidth= imageInfo.getWidth();
        int picHeight= imageInfo.getHeight();
        double picScale= NumberUtil.round(picWidth*1.0 / picHeight*1.0,2).doubleValue();

        UploadPictureResult uploadPictureResult=new UploadPictureResult();
        uploadPictureResult.setUrl(cosClientConfig.getHost()+"/"+ uploadPath);
        uploadPictureResult.setPicName(FileUtil.mainName(originalFilename));
        uploadPictureResult.setPicSize(FileUtil.size(file));
        uploadPictureResult.setPicWidth(picWidth);
        uploadPictureResult.setPicHeight(picHeight);
        uploadPictureResult.setPicScale(picScale);
        uploadPictureResult.setPicFormat(imageInfo.getFormat());
        //返回
        return uploadPictureResult;
    }

    /**
     * 清理临时文件
     * @param file
     */
    public  void deleteTempFile(File file) {
        if (file !=null){
            //删除临时文件
            boolean deleteResult = file.delete();
            if (!deleteResult){
                log.error("file delete error,filepath={}",file.getAbsolutePath());
            }
        }
    }





}
